#include <string>
#include <memory>
#include <iostream>

/*      学习建造模式的使用
    以建造苹果笔记本为例子
    建造抽象笔记本类（computer:os ,display ,boar ,showparameter）
    建造具体类 --笔记本类
    抽象建造者 set ,build
    具体建造者类
    指挥者类construct build
*/

class Computer
{
public:
    Computer() {}
    void set_dispaly(const std::string &display)
    {
        _display = display;
    }
    void set_board(const std::string &board)
    {
        _board = board;
    }

    virtual void set_os() = 0;
    void showPara()
    {
        std::string s = "笔记本参数:\n";
        s += "\t 显示器:" + _display+"\n";
        s += "\t 主板:" + _board+"\n";
        s += "\t 操作系统:" + _os;
        std::cout<<s<<std::endl;
    }

protected:
    std::string _display;
    std::string _board;
    std::string _os;
};

class MacBook : public Computer
{
public:
    void set_os() override
    {
        _os = "Mac-Os";
    }
};

// 建造零部件抽象类
class Builder
{
public:
    virtual void BuildDisplay(const std::string &display) = 0;
    virtual void BuildBoard(const std::string &board) = 0;
    virtual void BuildOs() = 0;
    virtual std::shared_ptr<Computer> Build() = 0;
};

// 具体类
class BuidlerMacBook : public Builder
{
public:
    BuidlerMacBook() : _cmp(new MacBook) {}

    void BuildDisplay(const std::string &display) override
    {
        _cmp->set_dispaly(display);
    }
    void BuildBoard(const std::string &board) override
    {
        _cmp->set_board(board);
    }
    void BuildOs()
    {
        _cmp->set_os();
    }
    std::shared_ptr<Computer> Build() override
    {
        return _cmp;
    }
private:
    std::shared_ptr<Computer> _cmp;
};

//指挥者
class Dirctor{
public:
    Dirctor(Builder* builder)
        :_builder(builder)
    {
    }
    void Construct(const std::string &display,const std::string &board)
    {
        _builder->BuildDisplay(display);
        _builder->BuildBoard(board);
        _builder->BuildOs();
    }
private:
    std::shared_ptr<Builder> _builder;
};

int main()
{
    Builder *build=new BuidlerMacBook();
    //指挥者
    std::unique_ptr<Dirctor> dirctor(new Dirctor(build));
    dirctor->Construct("sangxing","CHERRY");
    auto max=build->Build();
    max->showPara();
    return 0;
}